/*
 * author: Andriamananony, Meß, Falk
 */

package schedule;

import java.util.ArrayList;

import plan.Belegung;
import plan.Plan;
import util.Interval;
import auftrag.Auftrag;
import auftrag.Operation;
import auftrag.Produkt;
import auftrag.Ressource;
import auftrag.Variante;

public class EDF implements ISchedule {

	public Plan makePlan(ArrayList<?> pAuftragList, ArrayList<Ressource> pRessourceList) {
		// Plan der zurückgegeben wird
		Plan plaPlanA = new Plan();

		// Aktueller Auftrag aus der unsortierten Liste
		Auftrag aufAuftrag;

		// Liste erstellen mit Aufträgen die nach Priorität und Deadline
		// sortiert sind
		ArrayList<Auftrag> arrSortAuftrag = new ArrayList<Auftrag>();

		// Gehe alle Aufträge durch die unsortierte Liste durch
		for (int intIndexa = 0; intIndexa < pAuftragList.size(); intIndexa++) {

			// Lese den Auftrag ein, der einsortiert werden soll
			aufAuftrag = (Auftrag) pAuftragList.get(intIndexa);

			// Wenn die sortierte Liste noch leer ist, dann füge den ersten
			// Auftrag als Referenz ein
			if (arrSortAuftrag.isEmpty()) {
				arrSortAuftrag.add(aufAuftrag);
			} else {
				// Gucke die sortierte Liste durch
				for (int intIndexb = 0; intIndexb < arrSortAuftrag.size(); intIndexb++) {
					// Vergleiche ob die Priorität des Auftrages kleiner als die
					// der einsortierten Aufträge ist
					if (aufAuftrag.getPriority() > arrSortAuftrag
							.get(intIndexb).getPriority()) {
						arrSortAuftrag.add(intIndexb, aufAuftrag);
						intIndexb = arrSortAuftrag.size();
					}
					// Wenn die Priorität gleich ist und die Deadline kleiner
					// dann füge den Auftrag auch davor
					else if (aufAuftrag.getPriority() == arrSortAuftrag.get(
							intIndexb).getPriority()
							&& aufAuftrag.getDeadline() < arrSortAuftrag.get(
									intIndexb).getDeadline()) {
						arrSortAuftrag.add(intIndexb, aufAuftrag);
						intIndexb = arrSortAuftrag.size();
					}
					// Wenn beide Fälle nicht eintreffen und er am Ende der
					// Liste angekommen ist, dann füge einfach den Auftrag ein
					else if((intIndexb+1) >= arrSortAuftrag.size() ){
						arrSortAuftrag.add(aufAuftrag);
						intIndexb = arrSortAuftrag.size();
					}
				}
			}
		}

		int intIndexC;
		//Einplanung der sortierten Aufträge
		//intIndexA enthält immer den aktuellen Auftrag
		for(int intIndexA = 0; intIndexA < arrSortAuftrag.size(); intIndexA++) {
			Auftrag aufAuftragA = arrSortAuftrag.get(intIndexA);
			intIndexC = 0;
			//Plane die komplette Menge an Produkten ein
			for(int intIndexB = 0; intIndexB < aufAuftragA.getAuftragProdukteSize(); intIndexB++){
				Produkt proProduktA = aufAuftragA.getAuftragProdukte().get(intIndexB);
				if(proProduktA.getChosenVariante() == null)
					proProduktA.chooseVariant(intIndexC, false);
				Variante varVarianteA = proProduktA.getChosenVariante();
				intIndexC++;
				if(intIndexC >= proProduktA.getProduktVariante().size()) intIndexC = 0;
				//Plane erst eine komplette Variante ein
				for(int intIndexD = 1; intIndexD <= varVarianteA.getOperationSize(); intIndexD++) {
					Operation opeOperationA = varVarianteA.getOperation(intIndexD);
					Interval intIntervalA;
					if(opeOperationA.getPreviousOperation() == null)
						intIntervalA = opeOperationA.getRessource().getFirstUnoccupiedInterval(0, opeOperationA.getDuration());
					else {
						intIntervalA = opeOperationA.getRessource().getFirstUnoccupiedInterval(opeOperationA.getPreviousOperation().getInterval().getEnd(), opeOperationA.getDuration());
					}
					Belegung belBelegungA = new Belegung(opeOperationA, intIntervalA);
					plaPlanA.addBelegung(belBelegungA);
				}
			}
		}

		return plaPlanA;
	}
}